package me.arvin.qa.jmeter.plugins.dependscontroller;

import static me.arvin.qa.jmeter.plugins.dependscontroller.DependsManageThreadListener.addNodeDependsRelation;
import static me.arvin.qa.jmeter.plugins.dependscontroller.DependsManageThreadListener.getDependsResolveResult;

import java.lang.reflect.Field;
import java.util.LinkedHashSet;

import org.apache.jmeter.control.TransactionController;
import org.apache.jmeter.engine.StandardJMeterEngine;
import org.apache.jmeter.gui.tree.JMeterTreeNode;
import org.apache.jmeter.samplers.Sampler;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.TestStateListener;
import org.apache.jmeter.testelement.property.NullProperty;
import org.apache.jorphan.collections.HashTree;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DependsController extends TransactionController implements TestStateListener {

	private static final long serialVersionUID = -3917216026497293900L;

	protected static final Logger log = LoggerFactory.getLogger(DependsControllerGui.class);
	public static final String DependsRelationList = "DependsRelation";

	private static boolean dependsLisenerAdded = false;

	public DependsController() {
		super();
		setGenerateParentSample(true);
		setProperty(new DependsRelationProperty());
	}

	private boolean isDependsSuccess() {
		return getDependsResolveResult(getDependsRelationsProperty().getId());
	}

	DependsRelationProperty getDependsRelationsProperty() {
		return ((DependsRelationProperty) getProperty(DependsRelationList));
	}

	void setDependsRelations(LinkedHashSet<JMeterTreeNode> selecteds) {
		DependsRelationProperty myDependsRelations = getDependsRelationsProperty();

		LinkedHashSet<String> dependsList = new LinkedHashSet<>();
		for (JMeterTreeNode jMeterTreeNode : selecteds) {
			TestElement te = jMeterTreeNode.getTestElement();

			String dependsId;
			if (te.getProperty(DependsRelationList) instanceof NullProperty) {

				DependsRelationProperty TestElementDependsRelation = new DependsRelationProperty();
				TestElementDependsRelation.addBeDepends(myDependsRelations.getId());// 这个地方加的在哪删
				te.setProperty(TestElementDependsRelation);

				addNodeDependsRelation(jMeterTreeNode, TestElementDependsRelation);

				dependsId = TestElementDependsRelation.getId();

			} else {
				dependsId = ((DependsRelationProperty) te.getProperty(DependsRelationList)).getId();
			}
			dependsList.add(dependsId);
		}
		myDependsRelations.setDepends(dependsList);
	}

	@Override
	public Sampler next() {
		if (!isDependsSuccess()) {
			return null;
		}
		return super.next();
	}

	private static StandardJMeterEngine getEngine() {
		Thread currentThread = Thread.currentThread();

		Field field;
		try {
			field = Thread.class.getDeclaredField("target");
			field.setAccessible(true);
			Object object = field.get(currentThread);

			if (object instanceof StandardJMeterEngine) {
				return (StandardJMeterEngine) object;
			}
		} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
			e.printStackTrace();
		}

		return null;
	}

	@Override
	public void testStarted() {
		if (!dependsLisenerAdded) {
			if (isRunningVersion()) {
				try {
					Field field2 = StandardJMeterEngine.class.getDeclaredField("test");
					field2.setAccessible(true);
					Object object2 = field2.get(getEngine());
					HashTree testTree = (HashTree) object2;
					testTree.add(testTree.getArray()[0], DependsManageThreadListener.instance);
					testTree.traverse(DependsListenerTraverser.instance);
					dependsLisenerAdded = true;
				} catch (NoSuchFieldException | SecurityException | IllegalArgumentException
						| IllegalAccessException e) {
					e.printStackTrace();
				}
			}
		}

	}

	@Override
	public void testStarted(String host) {

	}

	@Override
	public void testEnded() {
		dependsLisenerAdded = false;

	}

	@Override
	public void testEnded(String host) {

	}

}